#include "bsp_usb.h"

extern otg_core_type otg_core_struct;
extern usbh_class_handler_type uhost_adb_class_handler;

extern void delay_ms(uint16_t nms);
extern void delay_us(uint32_t nus);

void usb_clock48m_select(usb_clk48_s clk_s)
{
  if(clk_s == USB_CLK_HICK)
  {
    crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);

    /* enable the acc calibration ready interrupt */
    crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);

    /* update the c1\c2\c3 value */
    acc_write_c1(7980);
    acc_write_c2(8000);
    acc_write_c3(8020);

    /* open acc calibration */
    acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
  }
  else
  {
    switch(system_core_clock)
    {
      /* 48MHz */
      case 48000000:
        crm_usb_clock_div_set(CRM_USB_DIV_1);
        break;

      /* 72MHz */
      case 72000000:
        crm_usb_clock_div_set(CRM_USB_DIV_1_5);
        break;

      /* 96MHz */
      case 96000000:
        crm_usb_clock_div_set(CRM_USB_DIV_2);
        break;

      default:
        break;

    }
  }
}

void USB_Init(void)
{
  gpio_init_type gpio_init_struct;
	
	usb_clock48m_select(USB_CLK_HEXT);
	
	crm_periph_clock_enable(OTG_CLOCK, TRUE);
  crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE);
	
  gpio_default_para_init(&gpio_init_struct);

  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;

	nvic_irq_enable(OTG_IRQ, 0, 0);
	
  usbh_init(&otg_core_struct,
            USB_FULL_SPEED_CORE_ID,
            USB_ID,
            &uhost_adb_class_handler,
            &usbh_user_handle);
}

void usb_delay_ms(uint32_t ms)
{
  delay_ms(ms);
}

void usb_delay_us(uint32_t us)
{
  delay_us(us);
}
